﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using Microsoft.Phone.Controls;
using QQConnectSdkSample.Model;
using QQConnectSdkSample.ViewModel;

namespace QQConnectSdkSample.ViewModel
{
    public class AuthenticationViewModel : IAuthProvider
    {
        private AuthenticationProcess _process;

        private object _sync = new object();

        public AuthenticationViewModel(AuthResult auth)
        {
            _process = new AuthenticationProcess()
           {
               Scope = "get_user_info,add_share,list_album,upload_pic,check_page_fans,add_t,add_pic_t,del_t,get_repost_list,get_info,get_other_info,get_fanslist,get_idolist,add_idol,del_idol,add_one_blog,add_topic,get_tenpay_addr"
           };

            _process.Authenticated += new EventHandler(_process_Authenticated);
            _process.AuthenticationFailed += new EventHandler(_process_AuthenticationFailed);
            _process.AuthResult = auth;

        }

        public bool HasAuthenticated
        {
            get
            {
                lock (_sync)
                    return _process.HasAuthenticated;
            }
        }

        public DateTime TokenExpiresAt
        {
            get
            {
                lock (_sync)
                {
                    if (HasAuthenticated)
                        return _process.AuthResult.ExpiresAt;
                }
                return DateTime.MinValue;
            }
        }

        private Uri _authUri = new Uri("about:blank");
        public Uri AuthUri
        {
            get
            {
                return _authUri;
            }
            set
            {
                if (_authUri != value)
                {
                    _authUri = value;
                    //RaisePropertyChanged("AuthUri");
                }
            }
        }


        private string _code;
        public string Code
        {
            get
            {
                return _code;
            }
            set
            {
                _code = value;
                _process.ExchangeCodeForToken(Code);
            }
        }

        private bool _isAuthenticating;
        private Queue<Action<string, string>> _queuedRequests = new Queue<Action<string, string>>();

        void _process_Authenticated(object sender, EventArgs e)
        {
            lock (_sync)
            {
                _isAuthenticating = false;

                while (_queuedRequests.Count > 0)
                    _queuedRequests.Dequeue()(_process.AuthResult.AccessToken, _process.AuthResult.OpenId);

                //ViewModelLocator.SaveSetting("auth", _process.AuthResult);
            }

            //RaisePropertyChanged("HasAuthenticated");
        }

        void _process_AuthenticationFailed(object sender, EventArgs e)
        {
            lock (_sync)
            {
                _isAuthenticating = false;
                _process.Revoke();
                //RaisePropertyChanged("HasAuthenticated");

                AuthUri = new Uri("about:blank");
                AuthUri = _process.AuthUri;
                MessageBox.Show("Please try again", "Login failed", MessageBoxButton.OK);
            }
        }

        public void GetAccessCode(Action<string, string> callback)
        {
            lock (_sync)
            {
                if (_isAuthenticating)
                {
                    _queuedRequests.Enqueue(callback);
                }
                else if (HasAuthenticated)
                {
                    if (!_process.AuthResult.IsExpired)
                    {
                        callback(_process.AuthResult.AccessToken, _process.AuthResult.OpenId);
                    }
                    else
                    {
                        InvokeCallback(callback);
                    }
                }
                else
                {
                    InvokeCallback(callback);
                }
            }
        }

        private void InvokeCallback(Action<string, string> callback)
        {
            _isAuthenticating = true;
            _queuedRequests.Enqueue(callback);

            ((PhoneApplicationFrame)App.Current.RootVisual).Navigate(new Uri("/AuthenticationPage.xaml", UriKind.Relative));
            AuthUri = _process.AuthUri;
        }


        public void Logout()
        {
            lock (_sync)
            {
                _process.Revoke();
            }
            //RaisePropertyChanged("HasAuthenticated");
        }


    }
}
